/**
 * 
 */
package com.csc.bankingsystem.core.dao.impl;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;

import org.apache.commons.collections.CollectionUtils;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Projections;
import org.springframework.beans.factory.annotation.Autowired;

import com.csc.bankingsystem.core.dao.GenericDAO;

/**
 * @author angelkid
 *
 */
public abstract class GenericDAOImpl<T> implements
		GenericDAO<T> {
	@Autowired
	SessionFactory sessionFactory;

	protected Session getSession(){
		return sessionFactory.getCurrentSession();
	}
	
	private Class<T> type;

	protected Class<T> getType() {
		return this.type;
	}

	protected String getClassName() {
		return type.getName();
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	public GenericDAOImpl() {
		Type t = getClass().getGenericSuperclass();
		ParameterizedType pt = (ParameterizedType) t;
		type = (Class) pt.getActualTypeArguments()[0];
	}

	public void delete(T obj) {
		getSession().delete(obj);
	}

	@SuppressWarnings("unchecked")
	public T find(long id) {
		return (T) getSession().get(type, id);
	}

	public Long save(T obj) {
		return (Long) getSession().save(obj);
	}

	public void update(T obj) {
		getSession().update(obj);
	}
	
	@SuppressWarnings("unchecked")
	public List<T> findAll() {
		
		Criteria criteria = getSession().createCriteria(type);
		List<T> list = criteria.list();
		return (CollectionUtils.isEmpty(list))?null:list;
	}

	public Long countAll() {
		return (Long) getSession().createCriteria(type).setProjection(Projections.rowCount()).uniqueResult();
	}
}

